import "reflect-metadata";
import {DECORATOR_FACTORY} from "./constant";
export const createParamDecorator = (keyOrFactory: string|Function) => {
    return (data?: any,...pipes:any[]) => {
        return (target: any, propertyKey: string, parameterIndex: number) => {
            // 如果data不是字符串，说明他不是一个对象的属性名，而是一个管道
            if(data && typeof data !== 'string'){
                pipes = [data,...pipes]
                data = null;
            }
            // 给控制器类的原型的propertyKey，也就是NestJs 方法属性上添加元数据
            // 属性名是params：NestJs 值是个数组，数组里因该存放数据，表示那个位置使用那个装饰器
            const existingParameters = Reflect.getMetadata('params', target, propertyKey) ?? [];
            // 从原型的方法属性上获取到参数类型的数组
            const metatype = Reflect.getMetadata('design:paramtypes', target, propertyKey)[parameterIndex];
            if(keyOrFactory instanceof Function){
                // 如果传递的是一个函数，存放参数索引，key固定DecoratorFactory表示装饰器工厂，factory工厂函数
                existingParameters[parameterIndex] = { parameterIndex, key:DECORATOR_FACTORY,factory:keyOrFactory, data ,pipes,metatype};
            }else{
                // ?? undefined null才会判断为false 0 '' 则是true
                existingParameters[parameterIndex] = { parameterIndex, key:keyOrFactory, data ,pipes,metatype};
            }
            Reflect.defineMetadata(`params`, existingParameters, target, propertyKey)
        };
    };
};
export const Request = createParamDecorator("Request");
export const Req = createParamDecorator("Req");
export const Query = createParamDecorator("Query")
export const Headers = createParamDecorator("Headers")
export const Session = createParamDecorator("Session")
export const Ip = createParamDecorator("Ip")
export const Param = createParamDecorator("Param")
export const Body = createParamDecorator("Body")
export const Res = createParamDecorator("Res")
export const Response = createParamDecorator("Response")
export const Next = createParamDecorator("Next")
export const UploadedFile = createParamDecorator("UploadedFile")
export const UploadedFiles = createParamDecorator("UploadedFiles")
